package basic.arch.component.bigdata.hbase.service

import basic.arch.component.bigdata.hbase.common.HbaseService
import basic.arch.component.bigdata.hbase.common.annotation.Table
import basic.arch.component.bigdata.hbase.entity.Car
import basic.arch.component.bigdata.hbase.entity.Person
import basic.arch.component.bigdata.hbase.entity.User
import basic.arch.component.bigdata.hbase.entity.User2
import org.apache.logging.log4j.core.config.ConfigurationSource
import org.apache.logging.log4j.core.config.Configurator
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.ContextConfiguration
import org.springframework.util.ResourceUtils
import spock.lang.Specification

@ContextConfiguration(locations = "classpath*:/spring/applicationContext-all.xml")
class HbaseServiceImplTest extends Specification {
    private static final Logger logger = LoggerFactory.getLogger(HbaseServiceImplTest.class)

    static {
        initLog4j2()
    }

    static void initLog4j2() {
        try {
            File cfgFile = ResourceUtils.getFile("classpath:log4j2.xml")
            ConfigurationSource source = new ConfigurationSource(new FileInputStream(cfgFile))
            Configurator.initialize(null, source)
        } catch (IOException e) {
            e.printStackTrace()
        }
    }

    @Autowired
    private HbaseService hbaseService

    def testSave() {
        Person person = new Person()
        String rowKey = "123456789"
        person.with {
            userName = "jannal"
            password = "123456"
            userId = rowKey
        }
        when: '测试单一对象存储，hbase shell 中通过scan "person" 查询结果是否正确'
        hbaseService.save(person)
        Person result = hbaseService.findOneByRowKeyValue(Person.class, rowKey)
        then:
        with(result) {
            "123456".equals(password) == true
            "jannal".equals(userName) == true
            "123456789".equals(rowKey) == true
        }
    }


    def testSaveNested() {
        def user = new User()
        String rowKey = "12345678910"
        user.with {
            userId = rowKey
            age = 11
            car = Car.newCar("宝马", 6L)
            email = "jannals@1263.com"
        }
        when: "存储嵌套对象"
        hbaseService.save(user)
        User result = hbaseService.findOneByRowKeyValue(User.class, rowKey)
        logger.info("返回结果:{}", result)
        then:
        with(result) {
            (11 == age) == true
            "12345678910".equals(rowKey) == true
            "jannals@1263.com".equals(email) == true
            "宝马".equals(car.getCarName()) == true
            (6L == car.getCarType()) == true
        }

    }

    def testFindAll() {
        when: "测试findAll"
        initPersonData(10)
        List<Person> personList = hbaseService.findAll(Person.class)
        logger.info("person表的信息如下:{}", personList)
        initUserData(10)
        List<User> userList = hbaseService.findAll(User.class)
        logger.info("user表的信息如下:{}", userList)
        then:
        1 == 1
    }

    def testSaveBatch() {
        when: "批量插入"
        List<Person> personList = new ArrayList<Person>()
        for (int i = 3000001; i < 30000000; i++) {
            Person person = new Person()
            person.setPassword("password-" + i * 1000000)
            person.setUserName("userName-" + i * 1000000)
            person.setUserId("2000000" + i)
            personList.add(person)
        }
        hbaseService.saveBatch(personList)
        then:
        1 == 1
    }


    def testFindOneByRowKeyValue() {
        when: "rowKey查询"
        def user = new User()
        String rowKey = "12345678911"
        user.with {
            userId = rowKey
            age = 100
            car = Car.newCar("宝马X", 10L)
            email = "jannals@126.com"
        }
        hbaseService.save(user)
        long startTime = System.nanoTime()
        User userResult = hbaseService.findOneByRowKeyValue(User.class, rowKey)
        long endTime = System.nanoTime()
        logger.info("user:{},查询一条数据花费时间", userResult, (endTime - startTime) / (1000))
        then:
        with(userResult) {
            (100 == age) == true
            "12345678911".equals(rowKey) == true
            "jannals@126.com".equals(email) == true
            "宝马X".equals(car.getCarName()) == true
            (10L == car.getCarType()) == true
        }

        when: "rowKey查询"
        def user1 = new User()
        String rowKey1 = "12345678912"
        user1.with {
            userId = rowKey1
            age = 12
            car = Car.newCar("奔驰", 7L)
            email = "wumingxiaobao@126.com"
        }
        hbaseService.save(user1)
        startTime = System.nanoTime()
        userResult = hbaseService.findOneByRowKeyValue(User.class, rowKey1)
        endTime = System.nanoTime()
        logger.info("user:{},查询一条数据花费时间", userResult, (endTime - startTime) / (1000))
        then:
        with(userResult) {
            (12 == age) == true
            "12345678912".equals(rowKey1) == true
            "wumingxiaobao@126.com".equals(email) == true
            "奔驰".equals(car.getCarName()) == true
            (7L == car.getCarType()) == true
        }
    }


    def testFindFromStartToEndRowKey() {
        when: "rowkey范围查询"
        initUser2BigData(10)
        List<User2> list = hbaseService.findFromStartToEndRowKey(User2.class, "10000002", "10000005")
        logger.info("数据大小:{},数据{}", list.size(), list)
        then:
        1 == 1
    }

    def testDeleteRow() {
        when: "删除行"
        User user = hbaseService.findOneByRowKeyValue(User.class, "12345678910")
        logger.info("删除前user:{}", user)
        hbaseService.deleteRow(User.class.getAnnotation(Table.class).tableName(), "123456789", User.class.getAnnotation(Table.class).columnFamilyName())
        user = hbaseService.findOneByRowKeyValue(User.class, "123456789")
        logger.info("删除后user:{}", user)
        then:
        1 == 1
    }


    def testDeleteColumnFamily() {
        when: "删除列"
        hbaseService.deleteColumnFamily(User.class.getAnnotation(Table.class).tableName(), User.class.getAnnotation(Table.class).columnFamilyName())
        User user = hbaseService.findOneByRowKeyValue(User.class, "12345678910")
        logger.info("删除列后的user:{}", user)
        then:
        1 == 1
    }

    def testDropTable() {
        when: "删除表"
        hbaseService.dropTable(User.class.getAnnotation(Table.class).tableName())
        hbaseService.dropTable(Person.class.getAnnotation(Table.class).tableName())
        then:
        1 == 1
    }


    private void initPersonData(int max) {
        for (int i = 0; i < max; i++) {
            Person person = new Person()
            person.setPassword("password-" + i * 1000000)
            person.setUserName("userName-" + i * 1000000)
            person.setUserId("123456780" + i)
            hbaseService.save(person)
        }
    }

    private void initUserData(int max) {
        for (int i = 0; i < max; i++) {
            User user = new User()
            user.setUserId("123456780" + i)
            user.setAge(i + 30)
            Car car = new Car()
            car.setCarName("宝马" + i)
            car.setCarType((long) i * 10)
            user.setCar(car)
            user.setEmail(i * 10 + "jannals@126.com")
            hbaseService.save(user)
        }
    }

    private void initUser2BigData(int max) {
        List<User2> userList = new ArrayList<User2>()
        for (int i = 0; i < max; i++) {
            User2 user = new User2()
            user.setUserId("1000000" + i)
            user.setAge(i + 30)
            Car car = new Car()
            car.setCarName("宝马" + i)
            car.setCarType((long) i * 10)
            user.setCar(car)
            user.setEmail(i * 10 + "jannals@126.com")
            userList.add(user)
        }
        hbaseService.saveBatch(userList)
    }

}
